//! 原始标识符 (Raw Identifiers)
//!
//! 原始标识符允许你使用通常不能用作标识符的单词，通过在标识符前加上 `r#` 前缀。
//! 这在以下情况特别有用：
//! 1. 使用 Rust 关键字作为标识符
//! 2. 与不遵循最新 Rust 命名约定的旧代码交互
//! 3. 使用由外部工具生成的标识符

/// 1. 使用关键字作为标识符
///
/// 在某些情况下，你可能需要使用 Rust 关键字作为变量名或函数名
pub fn keywords_as_identifiers() {
    println!("=== 使用关键字作为标识符 ===");

    // 使用 match 作为变量名（match 是 Rust 关键字）
    let r#match = "这是一个match变量";
    println!("变量值: {}", r#match);

    // 使用 struct 作为函数名（struct 是 Rust 关键字）
    fn r#struct() -> &'static str {
        "这是struct函数"
    }

    println!("函数返回值: {}", r#struct());
}

/// 2. 与旧代码交互
///
/// 当与使用旧关键字的外部代码交互时，原始标识符很有用
pub fn interop_with_legacy_code() {
    println!("\n=== 与旧代码交互 ===");

    // 假设有一个外部库使用了新的 Rust 关键字
    // 但你的代码是用旧版本编写的
    let r#async = "异步操作";
    let r#await = "等待结果";

    println!("{} 和 {}", r#async, r#await);
}

/// 3. 使用外部工具生成的标识符
///
/// 某些代码生成工具可能会创建与 Rust 关键字冲突的标识符
pub fn code_generation() {
    println!("\n=== 代码生成 ===");

    // 模拟外部工具生成的代码
    struct GeneratedStruct {
        r#type: String, // type 是关键字
        r#fn: String,   // fn 是关键字
        r#mod: String,  // mod 是关键字
    }

    let item = GeneratedStruct {
        r#type: "用户".to_string(),
        r#fn: "处理".to_string(),
        r#mod: "用户模块".to_string(),
    };

    println!("类型: {}, 函数: {}, 模块: {}", item.r#type, item.r#fn, item.r#mod);
}

/// 4. 原始标识符的限制
///
/// 原始标识符不能用于某些特殊场景
pub fn raw_identifier_limitations() {
    println!("\n=== 原始标识符的限制 ===");

    // 原始标识符仍然必须遵循标识符的基本规则
    // 例如，它们不能以数字开头
    // let r#123 = "invalid"; // 这是错误的

    // 但可以在关键字后添加其他字符
    let r#match_result = "匹配结果";
    println!("变量值: {}", r#match_result);
}

/// 5. 不能用作原始标识符的特殊情况
///
/// 注意：某些关键字不能用作原始标识符，包括：
/// - crate
/// - self
/// - Self
/// - super
pub fn special_cases() {
    println!("\n=== 特殊情况 ===");

    println!("注意：crate、self、Self 和 super 不能用作原始标识符");

    // 正确的用法示例
    let r#type = "type keyword";
    let r#match = "match keyword";
    let r#struct = "struct keyword";

    println!("可以使用的原始标识符示例: {}, {}, {}", r#type, r#match, r#struct);
}

/// 6. 不能使用的原始标识符示例（注释形式展示错误）
///
/// 以下代码如果取消注释会编译失败：
/// ```text
/// // 以下代码会编译失败
/// let r#crate = "crate";  // error: `crate` cannot be a raw identifier
/// let r#self = "self";    // error: `self` cannot be a raw identifier
/// let r#Self = "Self";    // error: `Self` cannot be a raw identifier
/// let r#super = "super";  // error: `super` cannot be a raw identifier
/// ```
pub fn cannot_be_used_examples() {
    println!("\n=== 不能使用的原始标识符示例 ===");
    println!("以下关键字不能用作原始标识符:");
    println!("- crate");
    println!("- self");
    println!("- Self");
    println!("- super");
    println!("如果尝试使用它们作为原始标识符，会导致编译错误。");
}

/// 主演示函数
pub fn demonstrate_raw_identifiers() {
    keywords_as_identifiers();
    interop_with_legacy_code();
    code_generation();
    raw_identifier_limitations();
    special_cases();
    cannot_be_used_examples();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_keywords_as_identifiers() {
        // 只能测试函数是否能被调用，不能测试 println! 的输出
        keywords_as_identifiers();
    }

    #[test]
    fn test_interop_with_legacy_code() {
        interop_with_legacy_code();
    }

    #[test]
    fn test_code_generation() {
        code_generation();
    }

    #[test]
    fn test_raw_identifier_limitations() {
        raw_identifier_limitations();
    }

    #[test]
    fn test_special_cases() {
        special_cases();
    }

    #[test]
    fn test_cannot_be_used_examples() {
        cannot_be_used_examples();
        // 这个测试只是验证函数能被调用
        // 实际的编译错误示例在注释中展示
    }

    /// 测试不能使用的原始标识符（编译失败示例）
    ///
    /// 注意：这个测试被注释掉了，因为这些代码会导致编译失败
    /// ```compile_fail
    /// #[test]
    /// fn test_invalid_raw_identifiers() {
    ///     let r#crate = "crate";  // 这会导致编译错误
    ///     let r#self = "self";    // 这会导致编译错误
    ///     let r#Self = "Self";    // 这会导致编译错误
    ///     let r#super = "super";  // 这会导致编译错误
    /// }
    /// ```
    #[allow(dead_code)]
    fn _test_invalid_raw_identifiers() {
        // 这个函数只是用来展示不能使用的原始标识符
        // 实际代码被注释以避免编译错误
        /*
        let r#crate = "crate";  // error: `crate` cannot be a raw identifier
        let r#self = "self";    // error: `self` cannot be a raw identifier
        let r#Self = "Self";    // error: `Self` cannot be a raw identifier
        let r#super = "super";  // error: `super` cannot be a raw identifier
        */
    }
}
